package com.strongbj.iot.devices.smarrack.response.coder;

import com.strongbj.iot.devices.smarrack.message.SmarRackMessage;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;

/**
 * 资产-SmarRack资产定位模块拆包类
 * 
 * @author yuzhantao
 *
 */
public class SmarRackDecoder extends LengthFieldBasedFrameDecoder {
//	private final static Logger logger = LogManager.getLogger(SmarRackDecoder.class);
//	private final static SmarRackMessageFactory factory = new SmarRackMessageFactory();
	
	// 头部起始码 0x5a 0xa5
	private static final int HEADER_SIZE = 11;

	/**
	 * 高起始码
	 */
	private byte hStartCode;
	/**
	 * 低起始码
	 */
	private byte lStartCode;
	/**
	 * 后续长度
	 */
	private short dataLength;
	/**
	 * 命令码
	 */
	private byte command;
	/**
	 * 设备版本号
	 */
	private short devVersion;
	/**
	 * 4位设备ID
	 */
	private byte[] devId = new byte[4];
	/**
	 * 数据
	 */
	private byte[] body = new byte[] { 0 };

	/**
	 * 
	 * @param maxFrameLength
	 *            解码时，处理每个帧数据的最大长度
	 * @param lengthFieldOffset
	 *            该帧数据中，存放该帧数据的长度的数据的起始位置
	 * @param lengthFieldLength
	 *            记录该帧数据长度的字段本身的长度
	 * @param lengthAdjustment
	 *            修改帧数据长度字段中定义的值，可以为负数
	 * @param initialBytesToStrip
	 *            解析的时候需要跳过的字节数
	 * @param failFast
	 *            为true，当frame长度超过maxFrameLength时立即报TooLongFrameException异常，为false，读取完整个帧再报异常
	 */
	public SmarRackDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment,
			int initialBytesToStrip, boolean failFast) {
		super(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast);
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		super.channelInactive(ctx);
		ByteBuf bf = this.internalBuffer();
		bf.release();
	}

	@Override
	protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
//		byte[] datas = new byte[in.readableBytes()];
//		in.readBytes(datas);
//		System.out.println(ByteUtil.byteArrToHexString(datas));
//		return null;
//		
		if (in == null) {
			return null;
		}

		if (in.readableBytes() < HEADER_SIZE) {
			return null;
		}
		if (body != null) { // body不等于空说明上一次读到完整数据了
			// 读取高起始码
			hStartCode = in.readByte();
			if (hStartCode != Integer.valueOf("FE", 16).byteValue()) {
				return null;
			}
			// 读取低起始码
			lStartCode = in.readByte();
			if (lStartCode != Integer.valueOf("FE", 16).byteValue()) {
				return null;
			}

			this.dataLength = in.readShort(); // 读取后续长度
			// System.out.println("当前dataLength:"+this.dataLength);
		}

		// 如果接收到的缓存数据小于协议数据长度，就返回空
		// System.out.println("当前数据长度:"+in.readableBytes());
		if (in.readableBytes() < this.dataLength) {
			body = null;
			return null;
		} else {
			this.command = in.readByte(); // 读取命令吗
			// System.out.println("当前command:"+ByteUtil.byteArrToHexString(new byte[]{
			// this.command}));
			this.devVersion = in.readShort(); // 读取设备版本号
			in.readBytes(this.devId); // 读取设备ID
			// System.out.println("当前devId:"+ByteUtil.byteArrToHexString(this.devId));

			// 数据长度=后续数据长度-命令码(1)-设备版本号(2)-设备ID(4)长度
			body = new byte[this.dataLength - 7];
			in.readBytes(body);
		}
		SmarRackMessage srm = new SmarRackMessage(this.command, this.devVersion, this.devId, this.body);
//		logger.debug("[{}]接收数码人的原始数据:" ,++index, ByteUtil.byteArrToHexString(factory.parse(srm)));
		return srm;
	}
}
